﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.ComponentModel;

namespace Utilities.Extensions
{

    public static class PropertyExtensions
    {
        public static PropertyChangedEventArgs CreateChangeEventArgs<T>(this Expression<Func<T>> property)
        {
            var expression = property.Body as MemberExpression;
            var member = expression.Member;
            return new PropertyChangedEventArgs(member.Name);
        }

        public static string MakeString<T>(this Expression<Func<T>> property)
        {
            var expression = property.Body as MemberExpression;
            var member = expression.Member;
            return string.Format("{0} = {1} ", member.Name, property.ToString());
        }



        public static bool AddToDictionary<T>(this Expression<Func<T>> property, Dictionary<string, string> Dict)
        {
            var expression = property.Body as MemberExpression;
            var member = expression.Member;

            object Value = Expression.Lambda<Func<T>>(expression).Compile()();

            string value;
            if (Value.TryGetProperString(out value))
            {
                KeyValuePair<string, string> KeyValue = new KeyValuePair<string, string>(member.Name, (string)Value);
                Dict.Add(KeyValue.Key, KeyValue.Value);
                return true;
            }
            return false;
        }


        public static int GetHashCode<T>(this Expression<Func<T>> property, int result)
        {
            string value;
            var expression = property.Body as MemberExpression;
            var member = expression.Member;

            object Value = Expression.Lambda<Func<T>>(expression).Compile()();

            if (TryGetProperString(property, out value))
            {
                const int prime = 31;
                result = prime * result + ((value == null) ? 0 : value.GetHashCode());
                return result;
            }
            return result;
        }



        public static bool TryGetProperString<T>(this Expression<Func<T>> property, out string value)
        {
            value = null;
            var expression = property.Body as MemberExpression;
            var member = expression.Member;

            object Value = Expression.Lambda<Func<T>>(expression).Compile()();
            if (Value == null)
            {
                return false;
            }


            if (string.IsNullOrEmpty(value))
            {
                return false;
            }


            //switch (Type.(member.GetType()))
            switch (member.GetType().Name)
            {
                case "DateTime":
                    DateTime date = (DateTime)Value;
                      value = string.Format("{0}{1}{2}{3}{4}{5}", date.Year.ToString(), date.Month.ToString(), date.Day.ToString(), date.Hour.ToString(), date.Minute.ToString(),  date.Second.ToString());
                      break;
                case "Decimal":
                case "Boolean":
                case "Int32":
                case "String":
                    break;
                default:
                    value.Replace(@"_", @" ");
                    value.Replace(@"__", @"-");
                    value.Trim();
                    break;
            }
            return true;
        }


        public static bool TryGetProperString(object Value, out string value)
        {
            value = null;

            if (Value == null)
            {
                return false;
            }

            value = (string)Value;

            if (string.IsNullOrEmpty(value))
            {
                return false;
            }

            value.Replace(@"_", @" ");
            value.Replace(@"__", @"-");
            value.Trim();

            return true;
        }


        public static bool AddToDictionary<T>(this Expression<Func<T>> property, Dictionary<string, string> Dict, object Value)
        {
            var expression = property.Body as MemberExpression;
            var member = expression.Member;

            string value;
            if (Value.TryGetProperString(out value))
            {
                KeyValuePair<string, string> KeyValue = new KeyValuePair<string, string>(member.Name, (string)Value);
                Dict.Add(KeyValue.Key, KeyValue.Value);
                return true;
            }
            return false;
        }


        public static bool AreEqual<T>(this Expression<Func<T>> property1, Expression<Func<T>> property2)
        {
            var expression1 = property1.Body as MemberExpression;
            var member1 = expression1.Member;

            var expression2 = property2.Body as MemberExpression;
            var member2 = expression2.Member;


            if (member1.Name != member2.Name)
            {
                return false;
            }

            object Value1 = Expression.Lambda<Func<T>>(expression1).Compile()();
            object Value2 = Expression.Lambda<Func<T>>(expression2).Compile()();
            if (Value1 == null || Value2 == null)
            {
                return false;
            }

            if (Value1.Equals(Value2))
            {
                return true;
            }
            else
            {
                return false;
            }
        }

      
    }


    public static class ObjectExtension
    {
        public static bool TryGetProperString(this object Value, out string value)
        {
            value = null;

            if (Value == null)
            {
                return false;
            }

            value = (string)Value;

            if (string.IsNullOrEmpty(value))
            {
                return false;
            }

            value.Replace(@"_", @" ");
            value.Replace(@"__", @"-");
            value.Trim();

            return true;
        }


        public static int GetHashCode(this object Value, int result)
        {
            string value;
            if (Value.TryGetProperString(out value))
            {
                const int prime = 31;
                result = prime * result + ((value == null) ? 0 : value.GetHashCode());
                return result;
            }
            return result;
        }
    }
}

